package grpc

import (
	"context"
	"phanes/errors"
	"time"

	"github.com/alibaba/sentinel-golang/core/base"
	"github.com/asim/go-micro/plugins/registry/etcd/v4"
	"github.com/asim/go-micro/plugins/server/grpc/v4"
	"go-micro.dev/v4"
	"go-micro.dev/v4/registry"
	"go-micro.dev/v4/server"
	"phanes/config"
	"phanes/server/grpc/middleware"
)

func Init() micro.Option {

	opts := []server.Option{
		server.Name(config.Conf.Name + "-grpc"),
		server.Version(config.Conf.Version),
		server.RegisterTTL(time.Second * 30),
		server.RegisterInterval(time.Second * 15),
		server.Registry(etcd.NewRegistry(registry.Addrs(config.EtcdAddr))),
		server.WrapHandler(middleware.ServerTraceWrapper()),
		server.WrapHandler(middleware.NewHandlerWrapper(middleware.WithServerBlockFallback(
			func(ctx context.Context, request server.Request, blockError *base.BlockError) error {
				switch blockError.BlockType() {
				case base.BlockTypeFlow:
					return errors.New("Network congestion, please try again later")
				case base.BlockTypeCircuitBreaking:
					return errors.New("trigger fuse")
				case base.BlockTypeHotSpotParamFlow:
					return errors.New("Hotspot parameter current limit")
				case base.BlockTypeIsolation:
					return errors.New("Concurrency isolation current limiting")
				case base.BlockTypeSystemFlow:
					return errors.New("System current limit")
				case base.BlockTypeUnknown:
				}
				return errors.New("Unknown situation current limit")
			}),
		)),
		server.WrapHandler(middleware.Log()),
	}

	if config.Conf.Grpc.GrpcListen != "" {
		opts = append(opts, server.Address(config.Conf.Grpc.GrpcListen))
	}

	if config.Conf.Grpc.DiscoveryListen != "" {
		opts = append(opts, server.Advertise(config.Conf.Grpc.DiscoveryListen))
	}

	srv := grpc.NewServer(opts...)
	// register grpc services
	// example: utils.Throw(micro.RegisterHandler(srv, new(App)))

	// ⚠️Waring!!!: Your service struct Name Must seem to the .proto file service Name
	// utils.Throw(micro.RegisterHandler(srv, new(v1.User)))

	return micro.Server(srv)
}
